Skip to content

feat: support Pass-Secrets mapped names - #148

Open
pando85 wants to merge 31 commits into
mainfrom
feat/pass-secrets-mapping
Open

feat: support Pass-Secrets mapped names#148
pando85 wants to merge 31 commits into
mainfrom
feat/pass-secrets-mapping

Conversation

@pando85

@pando85 pando85 commented Sep 5, 2026

Copy link
Copy Markdown
Owner

Summary

Implements automatic, lazy read-path support for Pass-Secrets (.secrets.gpg) identity maps.

  • detects .secrets.gpg automatically at the nearest .gpg-id boundary; no setting or repository migration is required
  • reuses the existing PGP/passphrase/biometric flow through a dedicated unlock activity
  • keeps decrypted mappings process-local and clears them on screen-off
  • displays mapped names while preserving physical codename files as the stable storage identity
  • searches by both mapped names and physical codenames (exact, fuzzy, and strict-domain matching)
  • never inherits a parent map across a nested .gpg-id boundary
  • hides .secrets.gpg and .mask.gpg from password listings even when hidden contents are enabled
  • invalidates cached mappings when the encrypted map file changes
  • suppresses repeated automatic prompts after cancellation/failure for the current map version
  • keeps mapped labels out of launcher shortcuts and persisted intent metadata, which continue to use obfuscated physical paths
  • canonicalizes identity boundaries so map resolution cannot escape the repository through path aliases

Activation / UX

Support is capability-detected from the repository structure. Entering an identity that contains both .gpg-id and .secrets.gpg claims that map for lazy unlock. If the user cancels or it cannot be decrypted, APS falls back to the physical codenames and does not repeatedly prompt for the same map version.

Nested identities remain independent trust boundaries. A child .gpg-id without its own .secrets.gpg never falls back to its parent's map.

Tests

Adds coverage for:

  • normal stores with no Pass-Secrets metadata
  • root identity auto-detection
  • identity with .gpg-id but no .secrets.gpg
  • parser whitespace and = in descriptions
  • malformed/unsafe/empty/pending entries and Pass-Secrets key character constraints
  • duplicate map keys
  • normal mapping resolution
  • unmapped physical entries and orphan map entries
  • nested identities with and without their own maps
  • one-shot lazy unlock claiming
  • cancellation suppression and retry after map changes
  • stale-map invalidation
  • cache clearing behavior
  • metadata classification
  • repository-boundary enforcement
  • mapped display names while retaining physical searchability
  • duplicate logical labels with distinct physical identity
  • strict-domain matching through mapped descriptions and physical paths

The existing full unit-test suite and passkey compatibility suite also exercise the changed model/search code paths.

Scope

This PR is intentionally read-path focused. It does not make mutations (create/rename/move/delete) update .secrets.gpg, and it does not index .mask.gpg aliases yet. Those should be follow-ups rather than mixing map-aware CRUD into the initial compatibility layer.

For repositories with multiple independently protected identity maps, logical-name search can only use mappings that are unlocked in the current process; APS deliberately does not trigger a chain of authentication prompts for every nested identity merely to perform a global search.

Closes #145

@pando85
pando85 marked this pull request as ready for review September 5, 2026 06:21
@forkline-bot

forkline-bot Bot commented Sep 5, 2026

Copy link
Copy Markdown

Fix pushed:

The fix was already applied and pushed in commit e3e65429 — the unused password_creation_duplicate_error string resource was removed from strings.xml. Posted a brief comment to PR #148.

@forkline-bot

forkline-bot Bot commented Sep 5, 2026

Copy link
Copy Markdown

Fixed both compilation errors: replaced substringBefore(Regex(...)) with chained substringBefore('#').substringBefore('!') in PassSecretsMapWriter.kt, and confirmed EXTRA_PHYSICAL_FILE_NAME is properly defined in PasswordCreationActivity's companion object.

@forkline-bot

forkline-bot Bot commented Sep 5, 2026

Copy link
Copy Markdown

Fixed compilation error: substringBefore(Regex(...)) is not valid — Kotlin's String.substringBefore() only accepts Char or String. Replaced with chained substringBefore('#').substringBefore('!') in PassSecretsMapWriter.kt:127.

Replace stdlib runCatching with explicit try-catch for IOException
to satisfy slack-lint DenyListedApi rule that flags runCatching in
coroutine contexts due to CancellationException handling.
forkline-dev[bot] added 3 commits September 5, 2026 15:35
The aliases List<String> comparison in areContentsTheSame is safe
because Kotlin's List implements equals() with element-wise comparison.
…Service

Satisfies slack-lint ExceptionMessage rule requiring lazyMessage param.
Satisfies slack-lint ExceptionMessage rule requiring lazyMessage param.
@forkline-bot

forkline-bot Bot commented Sep 5, 2026

Copy link
Copy Markdown

CI Fix Failed

I was unable to automatically fix the CI failure.

Please review the CI logs and fix the issue manually.


Runner: 9b2b

1 similar comment
@forkline-bot

forkline-bot Bot commented Sep 5, 2026

Copy link
Copy Markdown

CI Fix Failed

I was unable to automatically fix the CI failure.

Please review the CI logs and fix the issue manually.


Runner: 9b2b

These strings were used by the old moveFile function which was replaced
by the PassSecrets-aware move implementation.
@forkline-bot

forkline-bot Bot commented Sep 5, 2026

Copy link
Copy Markdown

CI Fix Failed

I was unable to automatically fix the CI failure.

Please review the CI logs and fix the issue manually.


Runner: 9b2b

@forkline-bot

forkline-bot Bot commented Sep 5, 2026

Copy link
Copy Markdown

CI Fix Failed

I was unable to automatically fix the CI failure.

Please review the CI logs and fix the issue manually.


Runner: 9b2b

@forkline-bot

forkline-bot Bot commented Sep 5, 2026

Copy link
Copy Markdown

Removed 3 unused string resources (password_move_error_title, password_move_error_message, password_creation_duplicate_error) that were left over from code replaced by the PassSecrets-aware implementation.

@forkline-bot

forkline-bot Bot commented Sep 5, 2026

Copy link
Copy Markdown

Removed unused string resource password_creation_duplicate_error that was causing the lint failure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Support for pass-secrets extension (tree obfuscation mapping)

1 participant